home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / cuj9204.zip / 1004071A < prev    next >
Text File  |  1992-06-02  |  23KB  |  952 lines

  1. /******************************************************************************
  2. * Module    :   Lexical Analyzer --- Process the input text file into tokens
  3. *                   that the parser can understand.
  4. *
  5. *               Copyright (C) 1990 John W. M. Stevens, All Rights Reserved
  6. *
  7. * Routines  :   Lex     - Return the next token from the file.
  8. *               OpenPrg - Open the source file.
  9. *               ParsErr - Report a parsing error.
  10. *
  11. * Author    :   John W. M. Stevens
  12. ******************************************************************************/
  13.  
  14. #include    <stdio.h>
  15. #include    <stdlib.h>
  16. #include    <ctype.h>
  17. #include    <string.h>
  18.  
  19. #include    "lex.h"
  20.  
  21. /* Structure of trie branch.    */
  22. typedef struct  key_st  {
  23.     char    c;
  24.     TKNS    token;
  25.     struct  key_st  *child;
  26. } NODE;
  27.  
  28. /* Constants local to this file.    */
  29. #define     MAX_STR     256
  30. #define     NOT_FND     -2
  31.  
  32. /* Object Data. */
  33. static  char    word[MAX_STR + 1];  /* Last string analyzed.                */
  34. static  char    PrvWd[MAX_STR + 1]; /* Previous word.                       */
  35. static  int     LnNo = 0;           /* The current line number in the file. */
  36. static  FILE    *PrgFl;             /* File pointer.                        */
  37.  
  38. /* Trie data structure containing all the keywords and punctuation marks for
  39. *   the language being tokenized.
  40. */
  41. static
  42. NODE    T5[2] = {
  43.     {   ' ',             2, NULL    },
  44.     {   'n',        ACTION, NULL    }
  45. };
  46.  
  47. static
  48. NODE    T4[2] = {
  49.     {   ' ',             2, NULL    },
  50.     {   'o',             0, T5  }
  51. };
  52.  
  53. static
  54. NODE    T3[2] = {
  55.     {   ' ',             2, NULL    },
  56.     {   'i',             0, T4  }
  57. };
  58.  
  59. static
  60.  
  61. NODE    T2[2] = {
  62.     {   ' ',             2, NULL    },
  63.     {   't',             0, T3  }
  64. };
  65.  
  66. static
  67. NODE    T8[2] = {
  68.     {   ' ',             2, NULL    },
  69.     {   'r',         AFTER, NULL    }
  70. };
  71.  
  72. static
  73. NODE    T7[2] = {
  74.     {   ' ',             2, NULL    },
  75.     {   'e',             0, T8  }
  76. };
  77.  
  78. static
  79. NODE    T6[2] = {
  80.     {   ' ',             2, NULL    },
  81.     {   't',             0, T7  }
  82. };
  83.  
  84. static
  85. NODE    T9[2] = {
  86.     {   ' ',             2, NULL    },
  87.     {   'd',           AND, NULL    }
  88. };
  89.  
  90. static
  91. NODE    Te[2] = {
  92.     {   ' ',             2, NULL    },
  93.     {   'e',       ARCHIVE, NULL    }
  94. };
  95.  
  96. static
  97. NODE    Td[2] = {
  98.     {   ' ',             2, NULL    },
  99.     {   'v',             0, Te  }
  100. };
  101.  
  102. static
  103. NODE    Tc[2] = {
  104.     {   ' ',             2, NULL    },
  105.     {   'i',             0, Td  }
  106. };
  107.  
  108. static
  109. NODE    Tb[2] = {
  110.     {   ' ',             2, NULL    },
  111.     {   'h',             0, Tc  }
  112. };
  113.  
  114. static
  115. NODE    Ta[2] = {
  116.     {   ' ',             2, NULL    },
  117.     {   'c',             0, Tb  }
  118. };
  119.  
  120. static
  121.  
  122. NODE    T16[2] = {
  123.     {   ' ',             2, NULL    },
  124.     {   's',    ATTRIBUTES, NULL    }
  125. };
  126.  
  127. static
  128. NODE    T15[2] = {
  129.     {   ' ',             2, NULL    },
  130.     {   'e',             0, T16 }
  131. };
  132.  
  133. static
  134. NODE    T14[2] = {
  135.     {   ' ',             2, NULL    },
  136.     {   't',             0, T15 }
  137. };
  138.  
  139. static
  140. NODE    T13[2] = {
  141.     {   ' ',             2, NULL    },
  142.     {   'u',             0, T14 }
  143. };
  144.  
  145. static
  146. NODE    T12[2] = {
  147.     {   ' ',             2, NULL    },
  148.     {   'b',             0, T13 }
  149. };
  150.  
  151. static
  152. NODE    T11[2] = {
  153.     {   ' ',             2, NULL    },
  154.     {   'i',             0, T12 }
  155. };
  156.  
  157. static
  158. NODE    T10[2] = {
  159.     {   ' ',             2, NULL    },
  160.     {   'r',             0, T11 }
  161. };
  162.  
  163. static
  164. NODE    Tf[2] = {
  165.     {   ' ',             2, NULL    },
  166.     {   't',             0, T10 }
  167. };
  168.  
  169. static
  170. NODE    T1[6] = {
  171.     {   ' ',             6, NULL    },
  172.     {   'c',             0, T2  },
  173.     {   'f',             0, T6  },
  174.     {   'n',             0, T9  },
  175.     {   'r',             0, Ta  },
  176.     {   't',             0, Tf  }
  177. };
  178.  
  179. static
  180. NODE    T1b[2] = {
  181.     {   ' ',             2, NULL    },
  182.  
  183.     {   'e',        BEFORE, NULL    }
  184. };
  185.  
  186. static
  187. NODE    T1a[2] = {
  188.     {   ' ',             2, NULL    },
  189.     {   'r',             0, T1b }
  190. };
  191.  
  192. static
  193. NODE    T19[2] = {
  194.     {   ' ',             2, NULL    },
  195.     {   'o',             0, T1a }
  196. };
  197.  
  198. static
  199. NODE    T18[2] = {
  200.     {   ' ',             2, NULL    },
  201.     {   'f',             0, T19 }
  202. };
  203.  
  204. static
  205. NODE    T17[2] = {
  206.     {   ' ',             2, NULL    },
  207.     {   'e',             0, T18 }
  208. };
  209.  
  210. static
  211. NODE    T23[2] = {
  212.     {   ' ',             2, NULL    },
  213.     {   'y',    DIRECTORY_T,    NULL    }
  214. };
  215.  
  216. static
  217. NODE    T22[2] = {
  218.     {   ' ',             2, NULL    },
  219.     {   'r',             0, T23 }
  220. };
  221.  
  222. static
  223. NODE    T21[2] = {
  224.     {   ' ',             2, NULL    },
  225.     {   'o',             0, T22 }
  226. };
  227.  
  228. static
  229. NODE    T20[2] = {
  230.     {   ' ',             2, NULL    },
  231.     {   't',             0, T21 }
  232. };
  233.  
  234. static
  235. NODE    T1f[2] = {
  236.     {   ' ',             2, NULL    },
  237.     {   'c',             0, T20 }
  238. };
  239.  
  240. static
  241. NODE    T1e[2] = {
  242.     {   ' ',             2, NULL    },
  243.  
  244.     {   'e',             0, T1f }
  245. };
  246.  
  247. static
  248. NODE    T1d[2] = {
  249.     {   ' ',             2, NULL    },
  250.     {   'r',             0, T1e }
  251. };
  252.  
  253. static
  254. NODE    T1c[2] = {
  255.     {   ' ',             2, NULL    },
  256.     {   'i',             0, T1d }
  257. };
  258.  
  259. static
  260. NODE    T26[2] = {
  261.     {   ' ',             2, NULL    },
  262.     {   'c',          EXEC, NULL    }
  263. };
  264.  
  265. static
  266. NODE    T25[2] = {
  267.     {   ' ',             2, NULL    },
  268.     {   'e',             0, T26 }
  269. };
  270.  
  271. static
  272. NODE    T24[2] = {
  273.     {   ' ',             2, NULL    },
  274.     {   'x',             0, T25 }
  275. };
  276.  
  277. static
  278. NODE    T2a[2] = {
  279.     {   ' ',             2, NULL    },
  280.     {   's',         FILES, NULL    }
  281. };
  282.  
  283. static
  284. NODE    T29[2] = {
  285.     {   ' ',             2, NULL    },
  286.     {   'e',             0, T2a }
  287. };
  288.  
  289. static
  290. NODE    T28[2] = {
  291.     {   ' ',             2, NULL    },
  292.     {   'l',             0, T29 }
  293. };
  294.  
  295. static
  296. NODE    T27[2] = {
  297.     {   ' ',             2, NULL    },
  298.     {   'i',             0, T28 }
  299. };
  300.  
  301. static
  302. NODE    T2f[2] = {
  303.     {   ' ',             2, NULL    },
  304.  
  305.     {   'n',        HIDDEN, NULL    }
  306. };
  307.  
  308. static
  309. NODE    T2e[2] = {
  310.     {   ' ',             2, NULL    },
  311.     {   'e',             0, T2f }
  312. };
  313.  
  314. static
  315. NODE    T2d[2] = {
  316.     {   ' ',             2, NULL    },
  317.     {   'd',             0, T2e }
  318. };
  319.  
  320. static
  321. NODE    T2c[2] = {
  322.     {   ' ',             2, NULL    },
  323.     {   'd',             0, T2d }
  324. };
  325.  
  326. static
  327. NODE    T2b[2] = {
  328.     {   ' ',             2, NULL    },
  329.     {   'i',             0, T2c }
  330. };
  331.  
  332. static
  333. NODE    T33[2] = {
  334.     {   ' ',             2, NULL    },
  335.     {   'l',         LABEL, NULL    }
  336. };
  337.  
  338. static
  339. NODE    T32[2] = {
  340.     {   ' ',             2, NULL    },
  341.     {   'e',             0, T33 }
  342. };
  343.  
  344. static
  345. NODE    T31[2] = {
  346.     {   ' ',             2, NULL    },
  347.     {   'b',             0, T32 }
  348. };
  349.  
  350. static
  351. NODE    T30[2] = {
  352.     {   ' ',             2, NULL    },
  353.     {   'a',             0, T31 }
  354. };
  355.  
  356. static
  357. NODE    T3a[2] = {
  358.     {   ' ',             2, NULL    },
  359.     {   'd',      MODIFIED, NULL    }
  360. };
  361.  
  362. static
  363. NODE    T39[2] = {
  364.     {   ' ',             2, NULL    },
  365.  
  366.     {   'e',             0, T3a }
  367. };
  368.  
  369. static
  370. NODE    T38[2] = {
  371.     {   ' ',             2, NULL    },
  372.     {   'i',             0, T39 }
  373. };
  374.  
  375. static
  376. NODE    T37[2] = {
  377.     {   ' ',             2, NULL    },
  378.     {   'f',             0, T38 }
  379. };
  380.  
  381. static
  382. NODE    T36[2] = {
  383.     {   ' ',             2, NULL    },
  384.     {   'i',             0, T37 }
  385. };
  386.  
  387. static
  388. NODE    T35[2] = {
  389.     {   ' ',             2, NULL    },
  390.     {   'd',             0, T36 }
  391. };
  392.  
  393. static
  394. NODE    T34[2] = {
  395.     {   ' ',             2, NULL    },
  396.     {   'o',             0, T35 }
  397. };
  398.  
  399. static
  400. NODE    T3d[2] = {
  401.     {   ' ',             2, NULL    },
  402.     {   'e',          NAME, NULL    }
  403. };
  404.  
  405. static
  406. NODE    T3c[2] = {
  407.     {   ' ',             2, NULL    },
  408.     {   'm',             0, T3d }
  409. };
  410.  
  411. static
  412. NODE    T3e[2] = {
  413.     {   ' ',             2, NULL    },
  414.     {   't',           NOT, NULL    }
  415. };
  416.  
  417. static
  418. NODE    T3b[3] = {
  419.     {   ' ',             3, NULL    },
  420.     {   'a',             0, T3c },
  421.     {   'o',             0, T3e }
  422. };
  423.  
  424. static
  425. NODE    T3f[2] = {
  426.  
  427.     {   ' ',             2, NULL    },
  428.     {   'r',            OR, NULL    }
  429. };
  430.  
  431. static
  432. NODE    T43[2] = {
  433.     {   ' ',             2, NULL    },
  434.     {   't',         PRINT, NULL    }
  435. };
  436.  
  437. static
  438. NODE    T42[2] = {
  439.     {   ' ',             2, NULL    },
  440.     {   'n',             0, T43 }
  441. };
  442.  
  443. static
  444. NODE    T41[2] = {
  445.     {   ' ',             2, NULL    },
  446.     {   'i',             0, T42 }
  447. };
  448.  
  449. static
  450. NODE    T40[2] = {
  451.     {   ' ',             2, NULL    },
  452.     {   'r',             0, T41 }
  453. };
  454.  
  455. static
  456. NODE    T4a[2] = {
  457.     {   ' ',             2, NULL    },
  458.     {   'y',      READONLY, NULL    }
  459. };
  460.  
  461. static
  462. NODE    T49[2] = {
  463.     {   ' ',             2, NULL    },
  464.     {   'l',             0, T4a }
  465. };
  466.  
  467. static
  468. NODE    T48[2] = {
  469.     {   ' ',             2, NULL    },
  470.     {   'n',             0, T49 }
  471. };
  472.  
  473. static
  474. NODE    T47[2] = {
  475.     {   ' ',             2, NULL    },
  476.     {   'o',             0, T48 }
  477. };
  478.  
  479. static
  480. NODE    T46[2] = {
  481.     {   ' ',             2, NULL    },
  482.     {   'd',             0, T47 }
  483. };
  484.  
  485. static
  486. NODE    T4d[2] = {
  487.  
  488.     {   ' ',             2, NULL    },
  489.     {   's',        RECURS, NULL    }
  490. };
  491.  
  492. static
  493. NODE    T4c[2] = {
  494.     {   ' ',             2, NULL    },
  495.     {   'r',             0, T4d }
  496. };
  497.  
  498. static
  499. NODE    T4b[2] = {
  500.     {   ' ',             2, NULL    },
  501.     {   'u',             0, T4c }
  502. };
  503.  
  504. static
  505. NODE    T45[3] = {
  506.     {   ' ',             3, NULL    },
  507.     {   'a',             0, T46 },
  508.     {   'c',             0, T4b }
  509. };
  510.  
  511. static
  512. NODE    T44[2] = {
  513.     {   ' ',             2, NULL    },
  514.     {   'e',             0, T45 }
  515. };
  516.  
  517. static
  518. NODE    T52[2] = {
  519.     {   ' ',             2, NULL    },
  520.     {   'h',        SEARCH, NULL    }
  521. };
  522.  
  523. static
  524. NODE    T51[2] = {
  525.     {   ' ',             2, NULL    },
  526.     {   'c',             0, T52 }
  527. };
  528.  
  529. static
  530. NODE    T50[2] = {
  531.     {   ' ',             2, NULL    },
  532.     {   'r',             0, T51 }
  533. };
  534.  
  535. static
  536. NODE    T55[2] = {
  537.     {   ' ',             2, NULL    },
  538.     {   't',        SELECT, NULL    }
  539. };
  540.  
  541. static
  542. NODE    T54[2] = {
  543.     {   ' ',             2, NULL    },
  544.     {   'c',             0, T55 }
  545. };
  546.  
  547. static
  548.  
  549. NODE    T53[2] = {
  550.     {   ' ',             2, NULL    },
  551.     {   'e',             0, T54 }
  552. };
  553.  
  554. static
  555. NODE    T4f[3] = {
  556.     {   ' ',             3, NULL    },
  557.     {   'a',             0, T50 },
  558.     {   'l',             0, T53 }
  559. };
  560.  
  561. static
  562. NODE    T59[2] = {
  563.     {   ' ',             2, NULL    },
  564.     {   'm',        SYSTEM, NULL    }
  565. };
  566.  
  567. static
  568. NODE    T58[2] = {
  569.     {   ' ',             2, NULL    },
  570.     {   'e',             0, T59 }
  571. };
  572.  
  573. static
  574. NODE    T57[2] = {
  575.     {   ' ',             2, NULL    },
  576.     {   't',             0, T58 }
  577. };
  578.  
  579. static
  580. NODE    T56[2] = {
  581.     {   ' ',             2, NULL    },
  582.     {   's',             0, T57 }
  583. };
  584.  
  585. static
  586. NODE    T4e[3] = {
  587.     {   ' ',             3, NULL    },
  588.     {   'e',             0, T4f },
  589.     {   'y',             0, T56 }
  590. };
  591.  
  592. static
  593. NODE    T0[21] = {
  594.     {   ' ',            21, NULL    },
  595.     {   '(',       L_PAREN, NULL    },
  596.     {   ')',       R_PAREN, NULL    },
  597.     {   ',',         COMMA, NULL    },
  598.     {   '/',       F_SLASH, NULL    },
  599.     {   'a',             0, T1  },
  600.     {   'b',             0, T17 },
  601.     {   'd',             0, T1c },
  602.     {   'e',             0, T24 },
  603.     {   'f',             0, T27 },
  604.     {   'h',             0, T2b },
  605.     {   'l',             0, T30 },
  606.     {   'm',             0, T34 },
  607.     {   'n',             0, T3b },
  608.     {   'o',             0, T3f },
  609.  
  610.     {   'p',             0, T40 },
  611.     {   'r',             0, T44 },
  612.     {   's',             0, T4e },
  613.     {   '{',       L_BRACE, NULL    },
  614.     {   '|',           BAR, NULL    },
  615.     {   '}',       R_BRACE, NULL    }
  616. };
  617.  
  618. /*-----------------------------------------------------------------------------
  619. | Routine   :   OpenPrg() --- Open the ASCII text file that contains the
  620. |                   back up program.
  621. |
  622. | Inputs    :   FileNm  - File name of source file.
  623. -----------------------------------------------------------------------------*/
  624.  
  625. void    OpenPrg(char    *FileNm)
  626. {
  627.     /* Open the program script file.    */
  628.     if ((PrgFl = fopen(FileNm, "rt")) == NULL)
  629.     {
  630.         fprintf(stderr, "OpenPrg (fopen) : Could not open file '%s' for "
  631.             "reading.\n", FileNm);
  632.         exit( -1 );
  633.     }
  634.  
  635.     /* Initialize object variables. */
  636.     *word = *PrvWd = '\0';
  637. }
  638.  
  639. /*-----------------------------------------------------------------------------
  640. | Routine   :   ParsErr() --- Report a parse error.
  641. |
  642. | Inputs    :   Err - Error string.
  643. -----------------------------------------------------------------------------*/
  644.  
  645. void    ParsErr(char    *Err)
  646. {
  647.     /* Print line number and error message. */
  648.     fprintf(stderr, "Error in Line: %d, %s.\n", LnNo + 1, Err);
  649.  
  650.     /* If there is a previous word, show it.    */
  651.     if ( *word )
  652.         fprintf(stderr, "\tOn or after word '%s'\n", word);
  653.     exit( -1 );
  654. }
  655.  
  656. /*-----------------------------------------------------------------------------
  657. | Routine   :   TrieSrch() --- Search the trie for a key word.
  658. |
  659. | Inputs    :   Trie    - The trie level pointer.
  660. |               ch      - The current character to search for.
  661. |               WordPtr - The pointer to the current byte of the word buffer.
  662. | Returns   :   Returns either a token value or
  663. |                   NOT_FND - For key word not found.
  664. |                   EOF     - For end of file.
  665. -----------------------------------------------------------------------------*/
  666.  
  667. static
  668. int     TrieSrch(NODE   *Trie,
  669.                  int    ch,
  670.  
  671.                  char   *WordPtr)
  672. {
  673.     register    int     mid;        /* Mid point of array piece.            */
  674.     register    TKNS    ret;        /* Return value of comparison.          */
  675.  
  676.     auto        int     lo;         /* Limits of current array piece for    */
  677.     auto        int     hi;         /*      binary search.                  */
  678.  
  679.     /* Make sure that input is lower case.  */
  680.     ch = tolower( ch );
  681.  
  682.     /* Search for a token.  */
  683.     hi = Trie[0].token - 1;
  684.     lo = 1;
  685.     do
  686.     {
  687.         /* Find mid point of current array piece.   */
  688.         mid = (lo + hi) >> 1;
  689.  
  690.         /* Do character comparison. */
  691.         ret = ch - Trie[mid].c;
  692.  
  693.         /* Fix the array limits.    */
  694.         if (ret <= 0)
  695.             hi = mid - 1;
  696.         if (ret >= 0)
  697.             lo = mid + 1;
  698.  
  699.     }  while (hi >= lo);
  700.  
  701.     /* If the character matches one of the entries in this level and this
  702.     *   entry has a child, recurse.  If a match is found but the matching
  703.     *   entry has no child, return the token value associated with the
  704.     *   match.  If the return value from the recursive call indicates that
  705.     *   no match was found at a lower level, return the token value
  706.     *   associated with the match at this level of the trie.
  707.     */
  708.     if (ret == 0)
  709.     {
  710.         /* Save the current character in the buffer for error reporting.    */
  711.         *WordPtr++ = ch;
  712.  
  713.         /* Are we looking for more characters in this string?   */
  714.         if ( Trie[mid].child )
  715.         {
  716.             /* Get the next character.  */
  717.             if ((ch = fgetc( PrgFl )) == EOF)
  718.                 return( EOF );
  719.  
  720.             /* Search next level.   */
  721.             if ((ret = TrieSrch(Trie[mid].child, ch, WordPtr)) == NOT_FND)
  722.             {
  723.                 ungetc(ch, PrgFl);
  724.                 return( Trie[mid].token );
  725.             }
  726.             return( ret );
  727.         }
  728.         else
  729.         {
  730.             /* Properly NUL terminate the buffer that the keyword is
  731.  
  732.             *   being saved in and return the token value.
  733.             */
  734.             *WordPtr = '\0';
  735.             return( Trie[mid].token );
  736.         }
  737.     }
  738.  
  739.     /* Terminate string in keyword buffer and return not found. */
  740.     *WordPtr = '\0';
  741.     return( NOT_FND );
  742.  
  743. }
  744.  
  745. /*-----------------------------------------------------------------------------
  746. | Routine   :   GetNo --- Get a number from the file.
  747. |
  748. | Inputs    :   word    - Pointer to word buffer for error reporting.
  749. | Outputs   :   RetNo   - Returns the number read from the file.
  750. |
  751. | Returns   :   Returns the last character read from the file or EOF.
  752. -----------------------------------------------------------------------------*/
  753.  
  754. static
  755. int     GetNo(char  **word,
  756.               long  *RetNo)
  757. {
  758.     auto        int     c;
  759.  
  760.     /* Get number.  */
  761.     *RetNo = 0L;
  762.     while ((c = fgetc( PrgFl )) >= '0' && c <= '9')
  763.     {
  764.         /* Save character in word buffer.   */
  765.         *(*word)++ = c;
  766.  
  767.         /* Calculate value of number.   */
  768.         *RetNo = *RetNo * 10L + (long) (c - '0');
  769.     }
  770.     return( c );
  771. }
  772.  
  773. /*-----------------------------------------------------------------------------
  774. | Routine   :   Lex() --- Get the next key word from the input file.
  775. |
  776. | Outputs   :   sym - The symbolic data read from the file.
  777. |
  778. | Returns   :   Returns the token read or EOF.
  779. -----------------------------------------------------------------------------*/
  780.  
  781. TKNS    Lex(TOKEN   *sym)
  782. {
  783.     register    int     i;
  784.     register    int     tkn;
  785.     auto        int     ch;
  786.     auto        char    *bf;
  787.  
  788.     /* Strip comments and white space.  If the character read is a '#',
  789.     *   every thing to the end of the line is a comment.
  790.     */
  791.     ch = fgetc( PrgFl );
  792.  
  793.     while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '#')
  794.     {
  795.         /* Process the special characters '#' and '\n'.     */
  796.         if (ch == '\n')
  797.             /* End of line, increment the line number.  */
  798.             LnNo++;
  799.         else if (ch == '#')
  800.         {
  801.             /* Found a comment character, strip all characters to end
  802.             *   of line and increment the line number.
  803.             */
  804.             while (fgetc( PrgFl ) != '\n')
  805.                 ;
  806.             LnNo++;
  807.         }
  808.  
  809.         /* Get the next character.  */
  810.         ch = fgetc( PrgFl );
  811.     }
  812.  
  813.     /* Get strings, etc.    */
  814.     if (ch == '"')
  815.     {
  816.         /* Get contents of string.  */
  817.         bf = sym->str;
  818.         for (i = 0; i < MAX_STR; i++)
  819.             if ((ch = fgetc( PrgFl )) != '"' && ch != EOF)
  820.                 *bf++ = ch;
  821.             else
  822.                 break;
  823.         *bf = '\0';
  824.  
  825.         /* Return string token. */
  826.         strcpy(word, sym->str);
  827.         return( STRING );
  828.     }
  829.     else if (ch >= '0' && ch <= '9')
  830.     {
  831.         auto        long        no;
  832.  
  833.         /* Establish a pointer to the word buffer and unget the
  834.         *   numeric character for re-reading.
  835.         */
  836.         bf = word;
  837.         ungetc(ch, PrgFl);
  838.  
  839.         /* Get number, time or date.    */
  840.         if ((ch = GetNo(&bf, &no)) == ':')
  841.         {
  842.             /* Getting time, not number.    */
  843.             *bf++ = ch;
  844.             sym->ftime.ti_hour = (unsigned char) no;
  845.             sym->ftime.ti_hund = (unsigned char) 0;
  846.  
  847.             /* Get minutes.     */
  848.             if ((ch = GetNo(&bf, &no)) == ':')
  849.             {
  850.                 /* Save minutes.    */
  851.                 *bf++ = ch;
  852.                 sym->ftime.ti_min = (unsigned char) no;
  853.  
  854.  
  855.                 /* Get seconds. */
  856.                 if ((ch = GetNo(&bf, &no)) == '.')
  857.                 {
  858.                     *bf = '\0';
  859.                     ParsErr( "Hundredths of seconds not allowed in "
  860.                         "time expressions" );
  861.                 }
  862.                 sym->ftime.ti_sec = (unsigned char) no;
  863.             }
  864.             else
  865.             {
  866.                 /* No seconds to get.   */
  867.                 sym->ftime.ti_min = (unsigned char) no;
  868.                 sym->ftime.ti_sec  = (unsigned char) 0;
  869.             }
  870.  
  871.             /* This is a time.  */
  872.             tkn = TIME;
  873.         }
  874.         else if (ch == '/')
  875.         {
  876.             /* Getting date, not number.    */
  877.             *bf++ = ch;
  878.             sym->fdate.da_mon = (char) no;
  879.  
  880.             /* Get day.     */
  881.             if ((ch = GetNo(&bf, &no)) == '/')
  882.             {
  883.                 /* Save character.  */
  884.                 *bf++ = ch;
  885.                 sym->fdate.da_day = (char) no;
  886.  
  887.                 /* Get year.    */
  888.                 ch = GetNo(&bf, &no);
  889.                 if (no > 1980L)
  890.                     no -= 1980L;
  891.                 else if (no > 80L && no < 100L)
  892.                     no -= 80L;
  893.                 else
  894.                 {
  895.                     *bf = '\0';
  896.                     ParsErr( "Error, bad year value in date expression." );
  897.                 }
  898.                 sym->fdate.da_year = (int) no;
  899.             }
  900.             else
  901.             {
  902.                 *bf = '\0';
  903.                 ParsErr( "Missing year in date expression" );
  904.             }
  905.  
  906.             /* This is a date.  */
  907.             tkn = DATE;
  908.         }
  909.         else
  910.         {
  911.             /* Just an integer constant.    */
  912.             sym->no = no;
  913.             tkn = NUMBER;
  914.  
  915.         }
  916.  
  917.         /* Return the unused character. */
  918.         *bf = '\0';
  919.         ungetc(ch, PrgFl);
  920.         return( tkn );
  921.     }
  922.     else if (ch == EOF)
  923.         return( EOF );
  924.  
  925.     /* Call the trie search routine to return the next token, EOF
  926.     *   or NOT_FND.  If not found, print an error and quit.
  927.     */
  928.     if ((tkn = TrieSrch(T0, ch, word)) == NOT_FND)
  929.     {
  930.         /* Illegal first character in word. */
  931.         if ( *PrvWd )
  932.             fprintf(stderr, "Parse - Error in Line: %d, cannot identify "
  933.                 "word after '%s'.\n", LnNo + 1, PrvWd);
  934.         else
  935.             fprintf(stderr, "Parse - Error in Line: %d, cannot identify "
  936.                 "first word in file.\n", LnNo + 1);
  937.         exit( -1 );
  938.     }
  939.     else if (tkn == 0)
  940.     {
  941.         /* Illegal word.    */
  942.         fprintf(stderr, "Parse - Error in Line: %d, cannot identify "
  943.             "word '%s'.\n", LnNo + 1, word);
  944.         exit( -1 );
  945.     }
  946.     strcpy(PrvWd, word);
  947.  
  948.     /* Return the token found.  */
  949.     return( tkn );
  950. }
  951. /* End of File */
  952.